package mqttclient

import (
	"encoding/json"
	"errors"
	"fmt"
	"time"

	"go-zero-admin/apps/modules/iot/cmd/link/network"
	"go-zero-admin/apps/modules/iot/cmd/link/network/constant"

	mqtt "github.com/eclipse/paho.mqtt.golang"
)

var _ iMqttClientProvider = (*mqttClientProvider)(nil)

var (
	IMqttClientProvider = new(mqttClientProvider)
)

type (
	iMqttClientProvider interface {
		network.INetworkProvider
	}

	mqttClientProvider struct {
	}
)

func (m *mqttClientProvider) GetType() *network.NetworkType {
	networkType := new(network.NetworkType)
	networkType = networkType.Of(constant.MqttClient)
	return networkType
}

func (m *mqttClientProvider) CreateNetwork(properties any) (network.INetwork, error) {
	mqttClientProperties := properties.(*MqttClientProperties)

	// 创建网络组件
	var mqttClient = MqttClient{Id: mqttClientProperties.GetId()}
	err := m.initMqttClient(&mqttClient, mqttClientProperties)
	if err != nil {
		return nil, err
	}

	return &mqttClient, nil
}

func (m *mqttClientProvider) Reload(network any, properties any) (network.INetwork, error) {
	mqttClient := network.(*MqttClient)
	mqttClientProperties := properties.(*MqttClientProperties)

	// 创建网络组件
	err := m.initMqttClient(mqttClient, mqttClientProperties)
	if err != nil {
		return mqttClient, err
	}

	return mqttClient, nil
}

func (m *mqttClientProvider) CreateConfig(networkProperties *network.NetworkProperties) (any, error) {
	// 获取配置
	configurations := networkProperties.Configurations
	arr, err := json.Marshal(configurations)
	if err != nil {
		return nil, err
	}

	// 获取配置实体
	mqttClientProperties := new(MqttClientProperties)
	err = json.Unmarshal(arr, &mqttClientProperties)
	if err != nil {
		return nil, err
	}

	// 设置属性参数
	mqttClientProperties.Id = networkProperties.Id
	if !mqttClientProperties.Validate() {
		return nil, errors.New(fmt.Sprintf("MQTT启动失败：ID: %d, Err: %s", mqttClientProperties.Id, "配置属性不合法"))
	}

	return mqttClientProperties, nil
}

func (m *mqttClientProvider) IsReusable() bool {
	return false
}

// 初始化mqtt客户端
func (m *mqttClientProvider) initMqttClient(mqttClient *MqttClient, mqttClientProperties *MqttClientProperties) error {
	// 初始化客户端期间不可以订阅或发布
	mqttClient.SetLoading(true)

	// 创建mqttClient客户端
	client := mqtt.NewClient(m.convertMqttClientOptions(mqttClientProperties))
	err := mqttClient.SetClient(client)
	if err != nil {
		return err
	}
	token := client.Connect()

	// 处理返回结果 等待是否超时，如果等待3秒后超时自动返回false
	for !token.WaitTimeout(3 * time.Second) {
	}
	// 初始化客户端期间不可以订阅或发布 解除
	mqttClient.SetLoading(false)
	if err = token.Error(); err != nil {
		return errors.New(fmt.Sprintf("MQTT启动失败：ID: %d, Err: %+v", mqttClientProperties.Id, err))
	}

	return nil
}

// 转化配置
func (m *mqttClientProvider) convertMqttClientOptions(mqttClientProperties *MqttClientProperties) *mqtt.ClientOptions {
	options := mqtt.NewClientOptions()
	options.AddBroker(mqttClientProperties.GetRemoteAddress())
	options.SetClientID(mqttClientProperties.ClientId)
	if mqttClientProperties.Username != "" {
		options.SetUsername(mqttClientProperties.Username)
	}
	if mqttClientProperties.Password != "" {
		options.SetPassword(mqttClientProperties.Password)
	}

	return options
}
